package com.bluesky.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bluesky.common.Constants;
import com.bluesky.common.enums.StatusEnum;
import com.bluesky.common.exception.CustomException;
import com.bluesky.common.utils.ConfigUtils;
import com.bluesky.system.common.dto.SysConfigAddDTO;
import com.bluesky.system.common.dto.SysConfigEditDTO;
import com.bluesky.system.common.dto.SysConfigQueryDTO;
import com.bluesky.system.entity.SysConfig;
import com.bluesky.system.mapper.SysConfigMapper;
import com.bluesky.system.service.ISysConfigService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 系统配置 服务实现类
 * </p>
 *
 * @author Kevin
 * @since 2021-06-23
 */
@Service
public class SysConfigServiceImpl extends ServiceImpl<SysConfigMapper, SysConfig> implements ISysConfigService {

    @Override
    public IPage<SysConfig> page(Page reqPage, SysConfigQueryDTO req) {
        LambdaQueryWrapper<SysConfig> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigName()), SysConfig::getConfigName, req.getConfigName());
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigKey()), SysConfig::getConfigKey, req.getConfigKey());
        queryWrapper.orderByDesc(SysConfig::getCreatedTime);
        return this.page(reqPage, queryWrapper);
    }

    @Override
    public List<SysConfig> list(SysConfigQueryDTO req) {
        LambdaQueryWrapper<SysConfig> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigName()), SysConfig::getConfigName, req.getConfigName());
        queryWrapper.like(StrUtil.isNotBlank(req.getConfigKey()), SysConfig::getConfigKey, req.getConfigKey());
        queryWrapper.orderByDesc(SysConfig::getCreatedTime);
        return this.list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysConfigAddDTO req) {
        if (!this.checkUniqueConfigName(req.getConfigName(), null)) {
            throw new CustomException("参数名称已存在");
        }
        if (!this.checkUniqueConfigKey(req.getConfigKey(), null)) {
            throw new CustomException("参数键名已存在");
        }
        SysConfig entity = BeanUtil.copyProperties(req, SysConfig.class);
        this.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(SysConfigEditDTO req) {
        SysConfig sysConfig = this.getById(req.getId());
        if (StrUtil.startWith(sysConfig.getConfigKey(), Constants.SYS_CONFIG_KEY) && !sysConfig.getConfigName().equals(req.getConfigName())) {
            throw new CustomException("系统内置参数，参数名称不允许修改");
        }
        if (StrUtil.startWith(sysConfig.getConfigKey(), Constants.SYS_CONFIG_KEY) && !sysConfig.getConfigKey().equals(req.getConfigKey())) {
            throw new CustomException("系统内置参数，参数键名不允许修改");
        }
        if (!this.checkUniqueConfigName(req.getConfigName(), req.getId())) {
            throw new CustomException("参数名称已存在");
        }
        if (!this.checkUniqueConfigKey(req.getConfigKey(), req.getId())) {
            throw new CustomException("参数键名已存在");
        }
        SysConfig entity = BeanUtil.copyProperties(req, SysConfig.class);
        this.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(String ids) {
        List<String> idList = Arrays.asList(ids.split(","));
        idList.forEach(item -> {
            SysConfig sysConfig = this.getById(item);
            if (StrUtil.startWith(sysConfig.getConfigKey(), Constants.SYS_CONFIG_KEY)) {
                throw new CustomException("系统内置参数不允许删除");
            }
        });
        this.removeByIds(Arrays.asList(ids.split(",")));
    }

    @Override
    public SysConfig view(String id) {
        return this.getById(id);
    }

    @Override
    public String getConfigValueByKey(String key) {
        String cacheValue = ConfigUtils.getConfigValue(key);
        if (StrUtil.isNotBlank(cacheValue)) {
            return cacheValue;
        }
        SysConfig sysConfig = this.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigKey, key).eq(SysConfig::getStatus, StatusEnum.YES.getCode()));
        if (Objects.isNull(sysConfig)) {
            return "";
        }
        ConfigUtils.setConfigCache(sysConfig.getConfigKey(), sysConfig.getConfigValue());
        return sysConfig.getConfigValue();
    }

    @Override
    public void loadAllConfig() {
        ConfigUtils.clearConfigCache();
        List<SysConfig> sysConfigList = this.list(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getStatus, StatusEnum.YES.getCode()));
        sysConfigList.forEach(item -> {
            ConfigUtils.setConfigCache(item.getConfigKey(), item.getConfigValue());
        });
    }

    private Boolean checkUniqueConfigName(String value, Long id) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysConfig entity = this.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigName, value).last("limit 1"));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

    private Boolean checkUniqueConfigKey(String value, Long id) {
        if (StrUtil.isBlank(value)) {
            return true;
        }
        id = Objects.isNull(id) ? -1L : id;
        SysConfig entity = this.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getConfigKey, value).last("limit 1"));
        return Objects.isNull(entity) || entity.getId().longValue() == id.longValue();
    }

}
